package com.gitee.wsl.platform.thread.task

import com.gitee.wsl.platform.exception.logOrRethrow
import org.jetbrains.annotations.ApiStatus
import java.util.*
import java.util.concurrent.Executor


/**
 * INTERNAL API.
 *
 *
 * **INTERNAL API:** Internal apis are subject to change or removal
 * without any notice. When code depends on internal APIs, it is subject to
 * breakage between minor version updates.
 */
@ApiStatus.Internal
internal object Trampoline {
    private val queue = ThreadLocal<ArrayDeque<Runnable>?>()

    private fun eventLoop() {
        while (true) {
            val current = queue.get() ?: return
            val next = current.pollFirst() ?: return
            try {
                next.run()
            } catch (e: Throwable) {
                e.logOrRethrow()
            }
        }
    }

    val INSTANCE: Executor = object : TaskExecutor {
        override fun resumeOnExecutor(runnable: Runnable) {
            execute(runnable)
        }

        override fun execute(command: Runnable) {
            var current = queue.get()
            if (current == null) {
                current = ArrayDeque<Runnable>()
                current.add(command)
                queue.set(current)
                try {
                    eventLoop()
                } finally {
                    queue.remove()
                }
            } else {
                current.add(command)
            }
        }
    }

    fun forkAll(executor: Executor) {
        val current = queue.get() ?: return

        val copy = ArrayDeque<Runnable>(current)
        executor.execute(Runnable {
            execute(Runnable {
                while (!copy.isEmpty()) {
                    val next = copy.pollFirst()
                    execute(next)
                }
            })
        })
    }

    fun execute(command: Runnable) {
        INSTANCE.execute(command)
    }
}


